Skip to content

feat: Outlook calendar cache#24539

Open
volnei wants to merge 23 commits intomainfrom
calendar-cache/office365
Open

feat: Outlook calendar cache#24539
volnei wants to merge 23 commits intomainfrom
calendar-cache/office365

Conversation

@volnei
Copy link
Copy Markdown
Contributor

@volnei volnei commented Oct 17, 2025

What does this PR do?

Introduces the CalendarCache for Office365


Summary by cubic

Adds Outlook (Office365) calendar cache with a new subscription adapter, a standardized webhook handshake, and reliable delta syncing in the cache window. Improves event parsing and token handling; the provider remains disabled by default until validated.

  • New Features

    • Office365 adapter: initial sync via calendarView/delta within the cache window; supports nextLink and deltaLink; improved parsing (busy/all‑day, time zones, etags, created/updated, recurring IDs); 7‑day subscription TTL.
    • Webhook: /api/webhooks/calendar-subscription/office365_calendar; handshake returns validationToken as text/plain; success responses return {}; validates clientState from headers/body.
    • Token management: MS_GRAPH_CLIENT_ID/MS_GRAPH_CLIENT_SECRET envs required for refresh; in‑memory refresh caching; supports delegated service‑account keys.
  • Refactors

    • Subscription job logs succeeded and failed counts.

Written for commit 4594507. Summary will update on new commits.

@github-actions
Copy link
Copy Markdown
Contributor

Hey there and thank you for opening this pull request! 👋🏼

We require pull request titles to follow the Conventional Commits specification and it looks like your proposed title needs to be adjusted.

Details:

No release type found in pull request title "wip Outlook calendar cache". Add a prefix to indicate what kind of release this pull request corresponds to. For reference, see https://www.conventionalcommits.org/

Available types:
 - feat: A new feature
 - fix: A bug fix
 - docs: Documentation only changes
 - style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
 - refactor: A code change that neither fixes a bug nor adds a feature
 - perf: A code change that improves performance
 - test: Adding missing tests or correcting existing tests
 - build: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)
 - ci: Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs)
 - chore: Other changes that don't modify src or test files
 - revert: Reverts a previous commit

@keithwillcode keithwillcode added core area: core, team members only foundation labels Oct 17, 2025
@volnei volnei changed the title wip Outlook calendar cache feat: Outlook calendar cache Oct 17, 2025
@vercel
Copy link
Copy Markdown

vercel bot commented Oct 17, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

3 Skipped Deployments
Project Deployment Review Updated (UTC)
cal Ignored Ignored Jan 6, 2026 11:45am
cal-companion Ignored Ignored Preview Jan 6, 2026 11:45am
cal-eu Ignored Ignored Jan 6, 2026 11:45am

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 3 files

Prompt for AI agents (all 1 issues)

Understand the root cause of the following 1 issues and fix them.


<file name="packages/features/calendar-subscription/adapters/Office365CalendarSubscription.adapter.ts">

<violation number="1" location="packages/features/calendar-subscription/adapters/Office365CalendarSubscription.adapter.ts:73">
If both MICROSOFT_WEBHOOK_URL and NEXT_PUBLIC_WEBAPP_URL are unset, this builds the truthy string &quot;undefined/api/webhooks/...&quot;, so subscribe() skips the missing-webhook guard and tries to register a Microsoft webhook against an invalid URL. Restore the null fallback (and config override) so we fail fast instead of sending a bad endpoint.</violation>
</file>

React with 👍 or 👎 to teach cubic. Mention @cubic-dev-ai to give feedback, ask questions, or re-run the review.

@github-actions github-actions bot added the ❗️ .env changes contains changes to env variables label Oct 19, 2025
devin-ai-integration bot and others added 2 commits October 19, 2025 11:42
- Fix import path for CalendarCacheEventService (use relative path)
- Fix 'throws error if webhook config is missing' test by stubbing all required env vars
- Fix 'performs full sync when no syncToken is present' test to match actual adapter behavior
- Add comprehensive test coverage for:
  - Token refresh and caching logic
  - Delegated credential service account key usage
  - parseEvents edge cases (different showAs values, cancelled events, all-day events)
  - refreshAccessToken error handling
  - Event filtering (events without id)

All 49 tests now passing (6 AdaptersFactory + 17 Google + 26 Office365)

Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
@volnei volnei marked this pull request as ready for review October 19, 2025 11:46
@graphite-app graphite-app bot requested review from a team October 19, 2025 11:47
@dosubot dosubot bot added calendar-apps area: calendar, google calendar, outlook, lark, microsoft 365, apple calendar ✨ feature New feature or request labels Oct 19, 2025
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 3 files

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

4 issues found across 8 files

Prompt for AI agents (all 4 issues)

Understand the root cause of the following 4 issues and fix them.


<file name="apps/web/app/api/webhooks/calendar-subscription/[provider]/route.ts">

<violation number="1" location="apps/web/app/api/webhooks/calendar-subscription/[provider]/route.ts:71">
Respond to the Office 365 validation handshake with the raw validationToken as plaintext; returning JSON causes Microsoft Graph to reject the handshake.</violation>
</file>

<file name="packages/features/calendar-subscription/lib/CalendarSubscriptionService.ts">

<violation number="1" location="packages/features/calendar-subscription/lib/CalendarSubscriptionService.ts:126">
Restoring the null return keeps the processWebhook contract for old subscriptions so callers/tests can detect stale channels.</violation>
</file>

<file name="packages/features/calendar-subscription/adapters/__tests__/Office365CalendarSubscriptionAdapter.test.ts">

<violation number="1" location="packages/features/calendar-subscription/adapters/__tests__/Office365CalendarSubscriptionAdapter.test.ts:77">
The tests replace global.fetch with vi.fn() in several cases but the afterEach teardown never restores the original fetch, so later suites will keep hitting the stub and can fail unexpectedly. Please capture the original fetch and reset it in afterEach.</violation>
</file>

<file name="packages/features/calendar-subscription/adapters/Office365CalendarSubscription.adapter.ts">

<violation number="1" location="packages/features/calendar-subscription/adapters/Office365CalendarSubscription.adapter.ts:72">
Rule violated: **Avoid Logging Sensitive Information**

Do not emit sensitive secrets in logs. Logging `this.webhookToken` exposes the MICROSOFT_WEBHOOK_TOKEN value, violating the policy against logging credentials. Remove the token from the log payload.</violation>
</file>

React with 👍 or 👎 to teach cubic. Mention @cubic-dev-ai to give feedback, ask questions, or re-run the review.

Comment thread apps/web/app/api/webhooks/calendar-subscription/[provider]/route.ts Outdated
Comment thread packages/features/calendar-subscription/lib/CalendarSubscriptionService.ts Outdated
Change expectation from toBeNull() to toBeUndefined() to match actual service behavior when processWebhook returns early for old subscriptions

Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
@github-actions
Copy link
Copy Markdown
Contributor

Devin AI is resolving merge conflicts

This PR has merge conflicts with the main branch. A Devin session has been created to automatically resolve them.

View Devin Session

Devin will:

  1. Merge the latest main into this branch
  2. Resolve any conflicts intelligently
  3. Run lint/type checks to ensure validity
  4. Push the resolved changes

If you prefer to resolve conflicts manually, you can close the Devin session and handle it yourself.

@github-actions
Copy link
Copy Markdown
Contributor

Devin AI is resolving merge conflicts

This PR has merge conflicts with the main branch. A Devin session has been created to automatically resolve them.

View Devin Session

Devin will:

  1. Merge the latest main into this branch
  2. Resolve any conflicts intelligently
  3. Run lint/type checks to ensure validity
  4. Push the resolved changes

If you prefer to resolve conflicts manually, you can close the Devin session and handle it yourself.

Resolved conflict in CalendarSubscriptionService.ts by keeping main's
implementation which includes proper channelId extraction and error handling
with span attributes for observability.

Co-Authored-By: unknown <>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Jan 14, 2026

E2E results are ready!

@volnei volnei marked this pull request as ready for review February 17, 2026 12:11
@volnei volnei enabled auto-merge (squash) February 17, 2026 12:27
@github-actions
Copy link
Copy Markdown
Contributor

Devin AI is completing this stale PR

This PR by @volnei has been marked as stale. A Devin session has been created to complete the remaining work.

View Devin Session


Devin will review the PR, address any feedback, and push updates to complete this PR.

- Fix webhookUrl to return null when env vars are unset instead of
  constructing an invalid URL with 'undefined' prefix
- Fix validate() to handle Microsoft Graph validationToken handshake
  (GET ?validationToken=...) before checking clientState
- Fix MICROSOFT_WEBHOOK_URL test env stub to use base URL (adapter
  appends the webhook path)
- Save/restore original global.fetch in test afterEach to prevent
  mock leakage between tests
- Add test for validationToken handshake validation
- Update .env.example: MS_GRAPH_CLIENT_ID/SECRET are required for
  Outlook calendar cache token refresh, not optional
- Apply biome lint/format fixes

Co-authored-by: Volnei Munhoz <volnei@munhoz.dev>
Co-Authored-By: unknown <>
@devin-ai-integration
Copy link
Copy Markdown
Contributor

Summary of changes addressing review feedback

I've completed the remaining fixes from the code review. Here's what was addressed:

Fixes applied

  1. webhookUrl null fallbackwebhookUrl now returns null when neither MICROSOFT_WEBHOOK_URL nor NEXT_PUBLIC_WEBAPP_URL is set, instead of constructing an invalid URL like "undefined/api/webhooks/...".

  2. validationToken handshake in validate() — Microsoft Graph subscription validation pings use GET ?validationToken=… without clientState. The validate() method now checks for validationToken in query params before checking clientState, so handshake requests pass validation correctly.

  3. Test fetch mock isolation — Saved/restored original global.fetch in afterEach to prevent mock leakage between tests. Fixed MICROSOFT_WEBHOOK_URL test env stub to use the base URL (the adapter appends the webhook path).

  4. Added test for validationToken handshake — New test verifying that requests with ?validationToken=abc123 are correctly validated.

  5. .env.example comments — Removed "Optional" prefix from MS_GRAPH_CLIENT_ID and MS_GRAPH_CLIENT_SECRET comments since they're required for Outlook calendar cache token refresh.

Previously fixed (by @volnei)

  • Validation token response format (plaintext, not JSON) — commit f6580d9
  • Sensitive info removed from logs — commits cd99cae, 6c6bf07

Notes

  • Type check errors in packages/embeds/embed-react are pre-existing and unrelated to this PR.
  • All 27 unit tests pass locally.

auto-merge was automatically disabled April 15, 2026 14:34

Pull request was closed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

calendar-apps area: calendar, google calendar, outlook, lark, microsoft 365, apple calendar core area: core, team members only devin-finish-pr ❗️ .env changes contains changes to env variables ✨ feature New feature or request foundation ready-for-e2e size/XL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants